Skip to content

feat: add TabsIcon component family with icon tabs, scroll overflow detection, and collapse animation#29684

Merged
vinnyhoward merged 10 commits into
mainfrom
feat-tmcu-591-homepage-hub-tabs-components
May 6, 2026
Merged

feat: add TabsIcon component family with icon tabs, scroll overflow detection, and collapse animation#29684
vinnyhoward merged 10 commits into
mainfrom
feat-tmcu-591-homepage-hub-tabs-components

Conversation

@vinnyhoward
Copy link
Copy Markdown
Contributor

@vinnyhoward vinnyhoward commented May 4, 2026

Description

Adds new TabsIcon components to components-temp and new icons to the component library as part of the hub page discovery tabs A/B test. Extracted into its own PR so it can be reviewed and merged independently before the feature PR lands.


TabsIcon Component Family

TabsIconTab
Tab item that renders an icon above a label. Icon and label have active/disabled color states. Supports a fillWidth prop for equal-width layouts and animated icon collapse via TabsIconAnimationContext.

TabsIconBar
Tab bar built for icon+label tabs. Features:

  • Automatic overflow detection — switches between a fixed layout and a horizontally scrollable ScrollView
  • Animated sliding underline indicator
  • fillWidth mode for equal-width tabs
  • Height collapse animation for hiding the bar on scroll

TabsIconList
Lazy-mounting tab list that manages active state, swipe gestures, and InteractionManager-based content loading. Per-tab keepMounted prop controls whether inactive tab content stays mounted or is unmounted when the tab loses focus.

TabsIconAnimationContext
React context that carries an Animated.Value (0 = icons expanded, 1 = collapsed) from a parent provider down to TabsIconTab without prop drilling.


Icons

Adds three new SVG icons and registers them in Icon.assets.ts / Icon.types.ts:

Icon IconName
Portfolio IconName.Portfolio
Predict IconName.Predict
Candlestick IconName.Candlestick

Changelog

CHANGELOG entry: null

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-591

Manual testing steps

Feature: Tabs component library

  Scenario: user navigates between tabs
    Given the app is open on any screen using TabsList
    When user taps each tab
    Then the animated underline slides to the active tab
    And the correct tab content is displayed

  Scenario: tabs overflow to scrollable mode
    Given a TabsBar with more tabs than fit the container width
    When the screen renders
    Then the tab bar becomes horizontally scrollable
    And the active tab is scrolled into view automatically

  Scenario: new icons render correctly
    Given any view that uses the Icon component
    When IconName.Portfolio or IconName.Predict is passed
    Then the correct SVG icon is displayed

Screenshots/Recordings

Take from the feature branch using these components here

iOS

Dark Mode

dark_mode_ios.mov

Light Mode (No Gradient)

light_mode_ios.mov

Android

Dark Mode

dark_mode_android.mov

Light Mode (No Gradient)

light_mode_android.mov

Before

~

After

~

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Medium Risk
Adds new tab UI components plus shared layout/list hooks involving animations, gesture handling, and InteractionManager-based lazy loading; regressions would primarily impact navigation/UX in screens adopting these new components. Also extends the global IconName enum/assets, which can affect consumers if mis-registered.

Overview
Adds a new TabsIcon component family under components-temp:

TabsIconTab renders icon+label tabs with active/disabled states and optional icon collapse via TabIconAnimationContext, TabsIconBar manages underline animation plus auto scroll overflow detection and optional height collapse, and TabsIconList composes the bar with lazy-mounted tab content, disabled-tab handling, swipe gestures, and a small imperative ref API.

Introduces reusable hooks useTabsBarLayout (measures tab/container layouts, toggles scroll mode, drives underline animations, and resets/cleans up on layout/tab changes) and useTabsList (active index normalization, InteractionManager-backed lazy loading with timeout fallback, key-preserving tab updates, and swipe-to-switch).

Extends the icon library by registering new SVGs and IconName entries (Group, Portfolio, Predictions) and updates the candlestick.svg asset. Comprehensive unit tests are added for the new components and hooks.

Reviewed by Cursor Bugbot for commit ffa57ba. Bugbot is set up for automated code reviews on this repo. Configure here.

Adds Tab, TabsBar, and TabsList to components-temp with animated underline,
scrollable overflow detection, icon support, and height collapse animation.
Adds Candlestick, Portfolio, and Predict icons.
@vinnyhoward vinnyhoward requested a review from a team as a code owner May 4, 2026 18:46
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbotv2 metamaskbotv2 Bot added the team-mobile-ux Mobile UX team label May 4, 2026
@github-actions github-actions Bot added the size-L label May 4, 2026
Comment thread app/component-library/components-temp/Tabs/TabsBar/TabsBar.tsx
Comment thread app/component-library/components-temp/Tabs/Tab/Tab.types.ts Outdated
Comment thread app/component-library/components-temp/Tabs/Tab/Tab.types.ts Outdated
@github-actions github-actions Bot added size-XL and removed size-L labels May 4, 2026
Comment thread app/component-library/components-temp/Tabs/TabsIconBar/TabsIconBar.tsx Outdated
Comment thread app/component-library/components-temp/Tabs/TabsIconBar/TabsIconBar.tsx Outdated
@vinnyhoward vinnyhoward changed the title feat: extend Tab, TabsBar, and TabsList components with icon support and scrollable overflow detection feat: add TabsIcon component family with icon tabs, scroll overflow detection, and collapse animation May 4, 2026
@vinnyhoward vinnyhoward added the skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. label May 4, 2026
Comment thread app/component-library/components/Icons/Icon/assets/candlestick.svg Outdated
@vinnyhoward vinnyhoward requested a review from brianacnguyen May 5, 2026 22:45
@vinnyhoward vinnyhoward requested review from a team as code owners May 6, 2026 00:07
@vinnyhoward vinnyhoward force-pushed the feat-tmcu-591-homepage-hub-tabs-components branch from 5c05f84 to 3fecb5b Compare May 6, 2026 00:11
@vinnyhoward vinnyhoward force-pushed the feat-tmcu-591-homepage-hub-tabs-components branch from 3fecb5b to 7d69b3d Compare May 6, 2026 00:15
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

🔍 Smart E2E Test Selection

  • Selected E2E tags: None (no tests recommended)
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: low
  • AI Confidence: 92%
click to see 🤖 AI reasoning details

E2E Test Selection:
The changes in this PR are purely additive component library additions with no production integration:

  1. New icon SVG assets (candlestick.svg, group.svg, pie-chart.svg, predictions.svg): New SVG files added to the icon assets directory. These are additive and don't modify any existing icons.

  2. Icon.types.ts & Icon.assets.ts: Added 3 new IconName enum values (Group, Portfolio, Predictions) with corresponding SVG mappings. These are purely additive — no existing enum values or mappings were changed.

  3. TabsIconBar, TabsIconList, TabsIconTab, hooks: Brand new UI components for icon-based tab navigation. Investigation confirmed these components are NOT exported from the main Tabs index.ts and are NOT imported by any production app code. They only appear in their own unit test files. No app screens, views, or features reference these components yet.

Since none of the changed code is integrated into any production user flows, no E2E tests are needed. The changes cannot break any existing test flows because:

  • No existing components were modified
  • No existing icon names were changed
  • The new tab components are completely isolated in the component library with no app-level consumers
  • The new icons are only referenced in the new isolated test files

No performance tests are needed either — the changes are additive SVG assets and isolated component library code with no impact on rendering pipelines, data loading, or critical user flows.

Performance Test Selection:
No performance impact expected. The changes are purely additive: new SVG icon assets and new isolated tab components that are not yet integrated into any production app screens. No existing rendering pipelines, data loading, or critical user flows are affected.

View GitHub Actions results

Copy link
Copy Markdown
Contributor

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ffa57ba. Configure here.

if (activeIndex >= 0 && layoutsReady) {
animateToTab(activeIndex);
}
}, [activeIndex, layoutsReady, animateToTab]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double animation fires on initialization due to dependency cycle

Medium Severity

The animateToTab callback includes isInitialized in its useCallback dependency array, and animateToTab itself is a dependency of the effect at line 156. When animateToTab is first called during initialization, it calls setIsInitialized(true) (line 136), which triggers a re-render, recreating animateToTab with a new closure. This new reference causes the effect to re-fire, calling animateToTab(activeIndex) a second time — now with isFirstTime = false, starting an unnecessary Animated.timing animation to the same position that was just set via setValue. In TabsIconBar, this also redundantly calls setUnderlineWidth and invokes the native animation bridge for a zero-delta animation.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ffa57ba. Configure here.

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 6, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
20.3% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@vinnyhoward vinnyhoward added this pull request to the merge queue May 6, 2026
Merged via the queue into main with commit 7da7450 May 6, 2026
58 of 60 checks passed
@vinnyhoward vinnyhoward deleted the feat-tmcu-591-homepage-hub-tabs-components branch May 6, 2026 00:57
@github-actions github-actions Bot locked and limited conversation to collaborators May 6, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.77.0 Issue or pull request that will be included in release 7.77.0 label May 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

release-7.77.0 Issue or pull request that will be included in release 7.77.0 size-XL skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. team-mobile-ux Mobile UX team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants